Skip to content

Add Stats API#48

Open
piobeny wants to merge 1 commit intomainfrom
stats-api
Open

Add Stats API#48
piobeny wants to merge 1 commit intomainfrom
stats-api

Conversation

@piobeny
Copy link

@piobeny piobeny commented Mar 6, 2026

Motivation

  • Add support for the Email Sending Stats API (/api/accounts/{account_id}/stats) to the Java SDK, enabling users to retrieve aggregated email sending statistics.

Changes

  • Add SendingStatsResponse model with delivery, bounce, open, click, and spam counts/rates (@JsonProperty annotated)
  • Add SendingStatGroupResponse model with dynamic field deserialization via @JsonAnySetter
  • Add StatsFilter builder class with startDate, endDate, and optional list filters (sendingDomainIds, sendingStreams, categories, emailServiceProviders)
  • Add Stats interface with 5 methods: getStats, byDomain, byCategory, byEmailServiceProvider, byDate
  • Add StatsImpl with query param serialization for array filters ([] suffix)
  • Wire Stats into MailtrapGeneralApi
  • Add unit tests with JSON fixtures
  • Update README with Stats API reference

How to test

  • stats.getStats(accountId, filter) with different filter parameters (startDate, endDate, sendingDomainIds, sendingStreams, categories, emailServiceProviders)
  • Test grouped endpoints (byDomain, byCategory, byEmailServiceProvider, byDate) with filters

Examples

import io.mailtrap.MailtrapClient;
import io.mailtrap.api.stats.Stats;
import io.mailtrap.api.stats.StatsFilter;
import io.mailtrap.model.response.stats.SendingStatsResponse;
import io.mailtrap.model.response.stats.SendingStatGroupResponse;

MailtrapClient client = MailtrapClient.builder()
    .apiKey("api_key")
    .build();

Stats stats = client.general().stats();
long accountId = 12345;

// Get aggregated stats
StatsFilter filter = StatsFilter.builder()
    .startDate("2026-01-01")
    .endDate("2026-01-31")
    .build();
SendingStatsResponse result = stats.getStats(accountId, filter);

// Get stats with filters
StatsFilter filteredFilter = StatsFilter.builder()
    .startDate("2026-01-01")
    .endDate("2026-01-31")
    .sendingDomainIds(List.of(1L, 2L))
    .sendingStreams(List.of("transactional"))
    .categories(List.of("Welcome email"))
    .emailServiceProviders(List.of("Gmail"))
    .build();
SendingStatsResponse filtered = stats.getStats(accountId, filteredFilter);

// Get stats grouped by date
List<SendingStatGroupResponse> byDate = stats.byDate(accountId, filter);

// Get stats grouped by category
List<SendingStatGroupResponse> byCategories = stats.byCategory(accountId, filter);

// Get stats grouped by email service provider
List<SendingStatGroupResponse> byEsp = stats.byEmailServiceProvider(accountId, filter);

// Get stats grouped by domain
List<SendingStatGroupResponse> byDomains = stats.byDomain(accountId, filter);

Summary by CodeRabbit

  • New Features

    • Added Stats API to retrieve sending statistics with metrics including delivery, bounce, open, click, and spam counts and rates.
    • Stats support filtering by date range and grouping by domain, category, email service provider, or date.
    • Added example demonstrating Stats API usage.
  • Tests

    • Added comprehensive test coverage for Stats API functionality.

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

This pull request adds a complete Stats API feature to the Mailtrap Java client library, including a new Stats interface and StatsImpl implementation for retrieving sending statistics grouped by domain, category, email service provider, or date. Supporting changes include two response DTOs, a StatsFilter data class, factory integration to wire Stats into the client, comprehensive tests with JSON fixtures, an example demonstrating usage, and relocation of the SendingStream enum to a common package.

Changes

Cohort / File(s) Summary
Stats API Core
src/main/java/io/mailtrap/api/stats/Stats.java, src/main/java/io/mailtrap/api/stats/StatsImpl.java
New Stats interface defining contract for retrieving statistics, and StatsImpl providing HTTP client implementation with methods for getStats, byDomain, byCategory, byEmailServiceProvider, and byDate. Includes URL building and query parameter construction from StatsFilter.
Response Models
src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java, src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java
Two new DTOs for deserializing stats API responses with Lombok and Jackson annotations; SendingStatsResponse maps delivery/bounce/open/click/spam metrics, SendingStatGroupResponse supports dynamic field mapping via @JsonAnySetter.
Filter & Supporting Data
src/main/java/io/mailtrap/api/stats/StatsFilter.java
New data class with builder pattern (Lombok) for filtering stats queries by date range, domain IDs, streams, categories, and email service providers.
Client Integration
src/main/java/io/mailtrap/factory/MailtrapClientFactory.java, src/main/java/io/mailtrap/client/api/MailtrapEmailSendingApi.java
Factory and client updated to instantiate StatsImpl and wire it into MailtrapEmailSendingApi via constructor parameter.
Package Reorganization
src/main/java/io/mailtrap/model/SendingStream.java, src/main/java/io/mailtrap/model/response/suppressions/SuppressionsResponse.java, src/test/java/io/mailtrap/api/suppressions/SuppressionsImplTest.java
SendingStream enum moved from response.suppressions to model package for broader reusability; import paths updated in dependent classes.
Tests & Fixtures
src/test/java/io/mailtrap/api/stats/StatsImplTest.java, src/test/resources/api/stats/*
New test class with five test methods validating each stats endpoint; five JSON fixture files provide mock responses for getStats, byDomain, byCategory, byEmailServiceProvider, and byDate.
Example
examples/java/io/mailtrap/examples/general/StatsExample.java
New example demonstrating Stats API usage by building config, creating client, constructing filter with date range, and calling all five stats methods with console output.

Sequence Diagram

sequenceDiagram
    participant User
    participant StatsAPI as StatsImpl
    participant HttpClient
    participant Server

    User->>StatsAPI: getStats(accountId, filter)
    StatsAPI->>StatsAPI: buildUrl("/stats")
    StatsAPI->>StatsAPI: buildStatsQueryParams(filter)
    StatsAPI->>HttpClient: GET /accounts/{id}/stats?startDate=...&endDate=...
    HttpClient->>Server: HTTP GET request
    Server-->>HttpClient: SendingStatsResponse JSON
    HttpClient-->>StatsAPI: Response
    StatsAPI-->>User: SendingStatsResponse

    User->>StatsAPI: byDomain(accountId, filter)
    StatsAPI->>StatsAPI: buildUrl("/domains")
    StatsAPI->>HttpClient: GET /accounts/{id}/stats/domains?...
    HttpClient->>Server: HTTP GET request
    Server-->>HttpClient: List<SendingStatGroupResponse> JSON
    HttpClient-->>StatsAPI: Response
    StatsAPI-->>User: List<SendingStatGroupResponse>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Implemented Suppressions API #35: Adds suppressions API component with similar MailtrapEmailSendingApi and MailtrapClientFactory integration pattern for wiring new API resources into the client.
  • Nitpick SDK updates #39: Modifies client wiring and example classes following the same factory construction pattern and example package structure as this Stats API addition.

Suggested reviewers

  • mklocek
  • vittorius
  • IgorDobryn

Poem

🐰 Hops with glee through stats so bright,
Domains, dates, and categories in sight!
Filter by stream, by sendingway,
API calls throughout the day!
Numbers grouped and metrics clear,
The Stats API is finally here! 📊✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.13% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Stats API' clearly and concisely summarizes the main change in the pull request, accurately reflecting the addition of the Email Sending Stats API to the Java SDK.
Description check ✅ Passed The pull request description includes Motivation, Changes, and How to test sections with code examples. While the template also includes Images/GIFs section, the core required information is present and comprehensive.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stats-api
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@piobeny piobeny requested review from VladimirTaytor and removed request for VladimirTaytor March 10, 2026 13:22
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java (1)

13-18: Guard against silently overwriting extra dynamic fields.

Every non-stats property replaces name and value. If this payload ever gains another top-level field, the first group key is lost with no signal. Consider rejecting a second dynamic key or storing extras explicitly instead of overwriting them.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java`
around lines 13 - 18, The current JsonAnySetter in SendingStatGroupResponse
(setDynamicField) blindly overwrites name/value for every non-"stats" key,
losing the first key; change setDynamicField to preserve the first encountered
dynamic key by: add a new Map<String,Object> extras field on
SendingStatGroupResponse, set name and value only if name is null (or blank) on
first non-"stats" key, and for any subsequent non-"stats" keys put them into
extras instead of overwriting; alternatively (if you prefer strictness) throw an
IllegalArgumentException when a second dynamic key is encountered—implement one
of these behaviors and update setDynamicField to check existing name before
mutating it and to populate extras (or throw) accordingly.
src/test/java/io/mailtrap/api/stats/StatsImplTest.java (1)

30-40: Add coverage for the list-filter query params.

These fixtures only assert start_date/end_date, but src/main/java/io/mailtrap/api/stats/StatsImpl.java:72-80 also serializes sending_domain_ids[], sending_streams[], categories[], and email_service_providers[]. If one of those keys is misspelled or emitted incorrectly, this suite still stays green.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/io/mailtrap/api/stats/StatsImplTest.java` around lines 30 - 40,
The tests only assert start_date/end_date; update the test to include the
list-filter query params that StatsImpl.serializeFilters emits
(sending_domain_ids[], sending_streams[], categories[],
email_service_providers[]) so the suite will catch misspellings: add those keys
with representative values to the defaultQueryParams Map used by TestHttpClient
(the variable currently named defaultQueryParams) and ensure each DataMock.build
entry in the TestHttpClient expectations includes those same keys (matching the
bracketed parameter names) so requests created by StatsImpl (methods in
StatsImpl that serialize filters around lines 72-80) must include the list
params to satisfy the mocks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/io/mailtrap/api/stats/StatsImpl.java`:
- Around line 72-80: Validate the incoming StatsFilter and its start/end dates
at the start of buildStatsQueryParams: check that filter is not null and that
filter.getStartDate() and filter.getEndDate() are non-null (or non-empty, per
domain rules) and throw a clear IllegalArgumentException if any are missing;
only after these checks keep the existing RequestData.buildQueryParams(...) with
Optional.ofNullable(...) calls. Reference: method buildStatsQueryParams and
class StatsFilter — add
Objects.requireNonNull/filter.getStartDate()/filter.getEndDate() checks or
explicit if-statements that throw with a descriptive message so callers fail
fast instead of producing an NPE or invalid request.

---

Nitpick comments:
In
`@src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java`:
- Around line 13-18: The current JsonAnySetter in SendingStatGroupResponse
(setDynamicField) blindly overwrites name/value for every non-"stats" key,
losing the first key; change setDynamicField to preserve the first encountered
dynamic key by: add a new Map<String,Object> extras field on
SendingStatGroupResponse, set name and value only if name is null (or blank) on
first non-"stats" key, and for any subsequent non-"stats" keys put them into
extras instead of overwriting; alternatively (if you prefer strictness) throw an
IllegalArgumentException when a second dynamic key is encountered—implement one
of these behaviors and update setDynamicField to check existing name before
mutating it and to populate extras (or throw) accordingly.

In `@src/test/java/io/mailtrap/api/stats/StatsImplTest.java`:
- Around line 30-40: The tests only assert start_date/end_date; update the test
to include the list-filter query params that StatsImpl.serializeFilters emits
(sending_domain_ids[], sending_streams[], categories[],
email_service_providers[]) so the suite will catch misspellings: add those keys
with representative values to the defaultQueryParams Map used by TestHttpClient
(the variable currently named defaultQueryParams) and ensure each DataMock.build
entry in the TestHttpClient expectations includes those same keys (matching the
bracketed parameter names) so requests created by StatsImpl (methods in
StatsImpl that serialize filters around lines 72-80) must include the list
params to satisfy the mocks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5a7ec49e-7893-457d-8a99-5d5d6a14e086

📥 Commits

Reviewing files that changed from the base of the PR and between 1136e25 and 145b5fe.

📒 Files selected for processing (14)
  • examples/java/io/mailtrap/examples/general/StatsExample.java
  • src/main/java/io/mailtrap/api/stats/Stats.java
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/main/java/io/mailtrap/api/stats/StatsImpl.java
  • src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java
  • src/main/java/io/mailtrap/factory/MailtrapClientFactory.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/test/java/io/mailtrap/api/stats/StatsImplTest.java
  • src/test/resources/api/stats/byCategory.json
  • src/test/resources/api/stats/byDate.json
  • src/test/resources/api/stats/byDomain.json
  • src/test/resources/api/stats/byEmailServiceProvider.json
  • src/test/resources/api/stats/getStats.json

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/main/java/io/mailtrap/api/stats/StatsImpl.java (1)

76-80: ⚠️ Potential issue | 🟡 Minor

Reject blank date values too.

Whitespace-only startDate / endDate still pass these checks and get sent as invalid query params. Trim or blank-check them here so callers fail fast.

Suggested fix
-        if (filter.getStartDate() == null || filter.getStartDate().isEmpty()) {
+        if (filter.getStartDate() == null || filter.getStartDate().trim().isEmpty()) {
             throw new IllegalArgumentException("startDate must not be null or empty");
         }
-        if (filter.getEndDate() == null || filter.getEndDate().isEmpty()) {
+        if (filter.getEndDate() == null || filter.getEndDate().trim().isEmpty()) {
             throw new IllegalArgumentException("endDate must not be null or empty");
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/io/mailtrap/api/stats/StatsImpl.java` around lines 76 - 80, The
current validation in StatsImpl (checks on filter.getStartDate() and
filter.getEndDate()) allows whitespace-only strings; update the validation to
reject blank values by trimming before emptiness check (e.g., if
(filter.getStartDate() == null || filter.getStartDate().trim().isEmpty()) and
similarly for getEndDate()) so callers fail fast and no whitespace-only dates
are sent as query params; keep throwing IllegalArgumentException with the same
messages.
🧹 Nitpick comments (1)
examples/java/io/mailtrap/examples/general/StatsExample.java (1)

19-22: Use placeholder dates in the sample.

A fixed January 2026 window will go stale and can easily return empty results for readers. Placeholder values or named constants keep the example evergreen.

Suggested tweak
-        final var filter = StatsFilter.builder()
-                .startDate("2026-01-01")
-                .endDate("2026-01-31")
+        final var filter = StatsFilter.builder()
+                .startDate("<START_DATE: YYYY-MM-DD>")
+                .endDate("<END_DATE: YYYY-MM-DD>")
                 .build();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/java/io/mailtrap/examples/general/StatsExample.java` around lines 19
- 22, The sample uses fixed dates in StatsFilter.builder() which will become
stale; replace the hard-coded "2026-01-01"/"2026-01-31" values in the
StatsExample's filter variable with placeholder constants or descriptive
variables (e.g., START_DATE/END_DATE or "YYYY-MM-DD" strings) and/or add a short
comment explaining they should be set by the user; update the
StatsFilter.builder().startDate(...) and .endDate(...) calls to use those
placeholders so the example remains evergreen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/main/java/io/mailtrap/api/stats/StatsImpl.java`:
- Around line 76-80: The current validation in StatsImpl (checks on
filter.getStartDate() and filter.getEndDate()) allows whitespace-only strings;
update the validation to reject blank values by trimming before emptiness check
(e.g., if (filter.getStartDate() == null ||
filter.getStartDate().trim().isEmpty()) and similarly for getEndDate()) so
callers fail fast and no whitespace-only dates are sent as query params; keep
throwing IllegalArgumentException with the same messages.

---

Nitpick comments:
In `@examples/java/io/mailtrap/examples/general/StatsExample.java`:
- Around line 19-22: The sample uses fixed dates in StatsFilter.builder() which
will become stale; replace the hard-coded "2026-01-01"/"2026-01-31" values in
the StatsExample's filter variable with placeholder constants or descriptive
variables (e.g., START_DATE/END_DATE or "YYYY-MM-DD" strings) and/or add a short
comment explaining they should be set by the user; update the
StatsFilter.builder().startDate(...) and .endDate(...) calls to use those
placeholders so the example remains evergreen.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 57307b4d-7843-4f9f-9cb8-b5f5cef595ec

📥 Commits

Reviewing files that changed from the base of the PR and between 145b5fe and 4c6ab63.

📒 Files selected for processing (14)
  • examples/java/io/mailtrap/examples/general/StatsExample.java
  • src/main/java/io/mailtrap/api/stats/Stats.java
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/main/java/io/mailtrap/api/stats/StatsImpl.java
  • src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java
  • src/main/java/io/mailtrap/factory/MailtrapClientFactory.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/test/java/io/mailtrap/api/stats/StatsImplTest.java
  • src/test/resources/api/stats/byCategory.json
  • src/test/resources/api/stats/byDate.json
  • src/test/resources/api/stats/byDomain.json
  • src/test/resources/api/stats/byEmailServiceProvider.json
  • src/test/resources/api/stats/getStats.json
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java
  • src/test/java/io/mailtrap/api/stats/StatsImplTest.java
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/test/resources/api/stats/getStats.json
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/test/resources/api/stats/byDomain.json
  • src/test/resources/api/stats/byEmailServiceProvider.json
  • src/main/java/io/mailtrap/api/stats/Stats.java
  • src/test/resources/api/stats/byDate.json
  • src/test/resources/api/stats/byCategory.json

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java (1)

17-23: ⚠️ Potential issue | 🟠 Major

Preserve the existing MailtrapGeneralApi constructor signature.

Adding a new final field under @RequiredArgsConstructor changes the public constructor from four args to five. That is a breaking SDK change for anyone instantiating MailtrapGeneralApi directly, even though this PR only adds a feature. Please keep the old overload around until the next major release, or switch this type away from Lombok-generated constructors so the public surface stays stable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java` around lines 17
- 23, The change added a new final field (stats) under `@RequiredArgsConstructor`
which changes MailtrapGeneralApi's public constructor signature and breaks
compatibility; fix by removing the Lombok-generated constructor and adding
explicit constructors: implement the original four-argument constructor
MailtrapGeneralApi(AccountAccesses accountAccesses, Accounts accounts, Billing
billing, Permissions permissions) that assigns those fields and sets stats to
null (preserving the old API), and add an additional five-argument constructor
MailtrapGeneralApi(AccountAccesses, Accounts, Billing, Permissions, Stats) that
assigns all fields; ensure the class-level `@RequiredArgsConstructor` is removed
so the explicit constructors are the only public ones.
🧹 Nitpick comments (1)
src/test/java/io/mailtrap/api/stats/StatsImplTest.java (1)

31-41: Add coverage for list-filter query serialization.

These mocks only verify start_date and end_date. The new behavior in this PR is the optional list filters with [] query keys, but none of the tests exercise sending_domain_ids[], sending_streams[], categories[], or email_service_providers[]. Please add at least one positive-path case that asserts those parameters are serialized correctly, since that is the easiest part of this feature to break.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/io/mailtrap/api/stats/StatsImplTest.java` around lines 31 - 41,
The current TestHttpClient mocks only assert start_date/end_date; add a
positive-path mock that verifies the new list-filter query serialization (keys
with []), e.g. create an expectedQueryParams map including
"sending_domain_ids[]", "sending_streams[]", "categories[]", and
"email_service_providers[]" mapped to their expected list values alongside
start_date/end_date, and add a DataMock.build entry that uses that map (similar
to existing builds) so the StatsImplTest (TestHttpClient/DataMock.build) asserts
those array-style query keys are sent correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java`:
- Around line 17-23: The change added a new final field (stats) under
`@RequiredArgsConstructor` which changes MailtrapGeneralApi's public constructor
signature and breaks compatibility; fix by removing the Lombok-generated
constructor and adding explicit constructors: implement the original
four-argument constructor MailtrapGeneralApi(AccountAccesses accountAccesses,
Accounts accounts, Billing billing, Permissions permissions) that assigns those
fields and sets stats to null (preserving the old API), and add an additional
five-argument constructor MailtrapGeneralApi(AccountAccesses, Accounts, Billing,
Permissions, Stats) that assigns all fields; ensure the class-level
`@RequiredArgsConstructor` is removed so the explicit constructors are the only
public ones.

---

Nitpick comments:
In `@src/test/java/io/mailtrap/api/stats/StatsImplTest.java`:
- Around line 31-41: The current TestHttpClient mocks only assert
start_date/end_date; add a positive-path mock that verifies the new list-filter
query serialization (keys with []), e.g. create an expectedQueryParams map
including "sending_domain_ids[]", "sending_streams[]", "categories[]", and
"email_service_providers[]" mapped to their expected list values alongside
start_date/end_date, and add a DataMock.build entry that uses that map (similar
to existing builds) so the StatsImplTest (TestHttpClient/DataMock.build) asserts
those array-style query keys are sent correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: abcddd79-cf5b-4bef-9f3e-edbb40ab278c

📥 Commits

Reviewing files that changed from the base of the PR and between 4c6ab63 and 929f573.

📒 Files selected for processing (14)
  • examples/java/io/mailtrap/examples/general/StatsExample.java
  • src/main/java/io/mailtrap/api/stats/Stats.java
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/main/java/io/mailtrap/api/stats/StatsImpl.java
  • src/main/java/io/mailtrap/client/api/MailtrapGeneralApi.java
  • src/main/java/io/mailtrap/factory/MailtrapClientFactory.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/test/java/io/mailtrap/api/stats/StatsImplTest.java
  • src/test/resources/api/stats/byCategory.json
  • src/test/resources/api/stats/byDate.json
  • src/test/resources/api/stats/byDomain.json
  • src/test/resources/api/stats/byEmailServiceProvider.json
  • src/test/resources/api/stats/getStats.json
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/test/resources/api/stats/byDomain.json
  • src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/main/java/io/mailtrap/api/stats/StatsImpl.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/main/java/io/mailtrap/api/stats/Stats.java
  • src/test/resources/api/stats/byDate.json
  • src/test/resources/api/stats/byCategory.json
  • src/test/resources/api/stats/byEmailServiceProvider.json

@piobeny piobeny requested review from IgorDobryn and mklocek March 13, 2026 07:03
final var stats = new StatsImpl(config);

return new MailtrapGeneralApi(accountAccess, accounts, billing, permissions);
return new MailtrapGeneralApi(accountAccess, accounts, billing, permissions, stats);
Copy link
Contributor

@mklocek mklocek Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make it part of sendingApi (similar like Suppressions and Sending Domains)

EDIT: And add a note about it to README

private String startDate;
private String endDate;
private List<Long> sendingDomainIds;
private List<String> sendingStreams;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use an enum for sendingStreams filter values

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
examples/java/io/mailtrap/examples/general/StatsExample.java (1)

1-43: LGTM!

The example clearly demonstrates usage of all Stats API methods with proper fluent API chaining. The placeholder values and date format comment provide good guidance for users.

Consider adding an example using optional filter parameters (e.g., sendingDomainIds, sendingStreams) to showcase the full filtering capability:

final var filterWithOptions = StatsFilter.builder()
        .startDate(START_DATE)
        .endDate(END_DATE)
        .sendingDomainIds(List.of(1L, 2L))
        .sendingStreams(List.of(SendingStream.TRANSACTIONAL))
        .build();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/java/io/mailtrap/examples/general/StatsExample.java` around lines 1
- 43, Add a second example showing optional StatsFilter parameters: create a new
variable (e.g., filterWithOptions) using StatsFilter.builder() and set
startDate/endDate plus sendingDomainIds (List.of(...)) and sendingStreams (e.g.,
SendingStream.TRANSACTIONAL) to demonstrate advanced filtering; call the same
client.sendingApi().stats() methods (getStats, byDomain, byCategory,
byEmailServiceProvider, byDate) with ACCOUNT_ID and filterWithOptions and add
necessary imports (java.util.List and the SendingStream enum) at the top of
StatsExample.java.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@examples/java/io/mailtrap/examples/general/StatsExample.java`:
- Around line 1-43: Add a second example showing optional StatsFilter
parameters: create a new variable (e.g., filterWithOptions) using
StatsFilter.builder() and set startDate/endDate plus sendingDomainIds
(List.of(...)) and sendingStreams (e.g., SendingStream.TRANSACTIONAL) to
demonstrate advanced filtering; call the same client.sendingApi().stats()
methods (getStats, byDomain, byCategory, byEmailServiceProvider, byDate) with
ACCOUNT_ID and filterWithOptions and add necessary imports (java.util.List and
the SendingStream enum) at the top of StatsExample.java.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3eeebb62-bd8f-48a4-b2e9-2a1cbea3e332

📥 Commits

Reviewing files that changed from the base of the PR and between 929f573 and 043e73e.

📒 Files selected for processing (17)
  • examples/java/io/mailtrap/examples/general/StatsExample.java
  • src/main/java/io/mailtrap/api/stats/Stats.java
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/main/java/io/mailtrap/api/stats/StatsImpl.java
  • src/main/java/io/mailtrap/client/api/MailtrapEmailSendingApi.java
  • src/main/java/io/mailtrap/factory/MailtrapClientFactory.java
  • src/main/java/io/mailtrap/model/SendingStream.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatGroupResponse.java
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/main/java/io/mailtrap/model/response/suppressions/SuppressionsResponse.java
  • src/test/java/io/mailtrap/api/stats/StatsImplTest.java
  • src/test/java/io/mailtrap/api/suppressions/SuppressionsImplTest.java
  • src/test/resources/api/stats/byCategory.json
  • src/test/resources/api/stats/byDate.json
  • src/test/resources/api/stats/byDomain.json
  • src/test/resources/api/stats/byEmailServiceProvider.json
  • src/test/resources/api/stats/getStats.json
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/io/mailtrap/model/response/suppressions/SuppressionsResponse.java
  • src/test/java/io/mailtrap/api/suppressions/SuppressionsImplTest.java
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/test/resources/api/stats/byCategory.json
  • src/test/resources/api/stats/byEmailServiceProvider.json
  • src/main/java/io/mailtrap/model/response/stats/SendingStatsResponse.java
  • src/test/resources/api/stats/byDate.json
  • src/main/java/io/mailtrap/api/stats/StatsFilter.java
  • src/test/java/io/mailtrap/api/stats/StatsImplTest.java
  • src/test/resources/api/stats/getStats.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants